<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    //环境配置，算法代码不在这里，请从91行开始阅读
    //一些常量，可以自定义修改
    const WIDTH = 100;
    const HEIGHT = 100;
    //不建议修改的常量
    const RED = "#FF0000";
    const GREEN = "#00FF00";
    const BLUE = "#0000FF";
    const BLACK = '#000000'
    //parpare environment:

    const canv = document.createElement('canvas');
    canv.id = 'canvas';
    canv.width = WIDTH << 2;
    canv.height = HEIGHT << 2;
    canv.style = 'border: 1px solid #000; display: block; margin: 0 auto';
    document.body.appendChild(canv);

    const ctx = canv.getContext('2d');

    function point(x, y, flag = true) {
      ctx.fillRect(x << 2, (HEIGHT - y) << 2, 4, 4);
      if (flag) {
        console.log('create a point (' + x + ',' + y + ')');
      }
    }

    function dda(x1, y1, x2, y2) { // 用dda方法绘制(x1,y1),(x2,y2)这条直线
      if (x1 === x2) { //特殊情况：没有k的时候
        let min = Math.min(y1, y2);
        let max = Math.max(y1, y2);
        for (let i = min; i <= max; i++) {
          point(x1, i);
        }
        return;
      }
      if (y1 === y2) { //特殊情况：没有k的时候
        let min = Math.min(x1, x2);
        let max = Math.max(x1, x2);
        for (let i = min; i <= max; i++) {
          point(i, y1);
        }
        return;
      }
      let k = (y2 - y1) / (x2 - x1);
      let x = 0;
      let y = 0;
      let temp = 0;
      if (Math.abs(k) > 1) { // |k|>1
        if (y1 > y2) { //调整1，2的位置，使y1一定要小于y2
          temp = y1;
          y1 = y2;
          y2 = temp;
          temp = x1;
          x1 = x2;
          x2 = temp;
        }
        k = (x2 - x1) / (y2 - y1);
        x = x1;
        for (y = y1; y <= y2; y++) {
          point(Math.trunc(x + 0.5), y);
          x = x + k;
        }
      } else { //|k|<=1
        if (x1 > x2) { //调整1，2的位置，使x1一定要小于x2
          temp = y1;
          y1 = y2;
          y2 = temp;
          temp = x1;
          x1 = x2;
          x2 = temp;
        }
        y = y1;
        for (x = x1; x <= x2; x++) {
          point(x, Math.trunc(y + 0.5), false);
          y = y + k;
        }
      }
    }
  </script>
  <div style="text-align: center; margin: 20px 0 20px 0; ">
    左边界：
    <input type="number" class="param" value="5">
    右边界：
    <input type="number" class="param" value="30"><br>
    上边界：
    <input type="number" class="param" value="30">
    下边界：
    <input type="number" class="param" value="5"><br>
    x1:
    <input type="number" class="param" value="1">
    y1:
    <input type="number" class="param" value="5"><br>
    x2:
    <input type="number" class="param" value="10">
    y2:
    <input type="number" class="param" value="10"><br>
    <button onclick="changeParam()">确认</button>
  </div>
  <div style="text-align: center;">
    <button onclick="printWithCohen()">使用Cohen-Sutherland算法切割</button>
    <button onclick="printWithMid()">使用中点分割算法切割</button>
    <button onclick="printWithLiang()">使用Barsky算法切割</button>
  </div>
  <div style="text-align: center; color: #666;" id="message">消息：<br/></div>
  <script>
    let mess = document.getElementById('message');
    function log(message) {
      mess.innerHTML += (message + '<br/>');
    }
    let l, r, t, b, x1, x2, y1, y2;
    function changeParam() {
      canv.width = canv.width;
      let params = document.getElementsByClassName('param');
      l = Number(params[0].value);
      r = Number(params[1].value);
      t = Number(params[2].value);
      b = Number(params[3].value);
      x1 = Number(params[4].value);
      y1 = Number(params[5].value);
      x2 = Number(params[6].value);
      y2 = Number(params[7].value);

      ctx.fillStyle = BLACK;
      for (let i = l; i <= r; i++) {
        point(i, t, false);
        point(i, b, false);
      }
      for (let i = b; i <= t; i++) {
        point(l, i, false);
        point(r, i, false);
      }

      log('可视窗口左边界: ' + l + ' 右边界: ' + r + ' 上边界: ' + t + ' 下边界: ' + b);
      log('对直线(' + x1 + ', ' + y1 + '), (' + x2 + ', ' + y2 + ')进行切割:');

      ctx.fillStyle = "#ccc";
      dda(x1, y1, x2, y2);
    }
    changeParam();
    ctx.fillStyle = "pink";
  </script>
  <script src="./算法代码在这里.js"></script>
</body>
<!--
  // Liang-Barsky算法辅助函数
    function LBLineClipTest(p, q, umax, umin) {
      let r = 0.0;
      if (p < 0.0) { //p小于0时比较最大值；
        r = q / p;
        if (r > umin) {
          return {
            umax,
            umin,
            res: false
          };
        } else if (r > umax) { //umax小于umin时直线段有在窗口内的部分；
          umax = r
        }
      } else if (p > 0.0) { //p大于0时比较最小值；
        r = q / p;
        if (r < umax) {
          return {
            umax,
            umin,
            res: false
          };
        } else if (r < umin) {
          umin = r;
        };
      } else if (q < 0.0) {//处理 p=0的情况；
        return {
          umax,
          umin,
          res: false
        };
      } 
      return {
        umax,
        umin,
        res: true
      };
    }

    function LBLineClip(left, right, bottom, top, x1, y1, x2, y2) {
      let umax;
      let umin;
      let deltax;
      let deltay;
      deltax = x2 - x1;
      deltay = y2 - y1;
      umax = 0.0;
      umin = 1.0;
      let temp = LBLineClipTest(-deltax, x1 - left, umax, umin);
      if (!temp.res) {console.log(1);
        return null;
      }
      temp = LBLineClipTest(deltax, right - x1, temp.umax, temp.umin);
      if (!temp.res) {console.log(2);
        return null;
      }
      temp = LBLineClipTest(-deltay, y1 - bottom, temp.umax, temp.umin);
      if (!temp.res) {console.log(3);
        return null;
      }
      temp = LBLineClipTest(deltay, top - y1, temp.umax, temp.umin);
      if (!temp.res) {console.log(4);
        return null;
      }
      x1 = Math.floor(x1 + temp.umax * deltax + 0.5);
      y1 = Math.floor(y1 + temp.umax * deltay + 0.5);
      x2 = Math.floor(x1 + temp.umin * deltax + 0.5);
      y2 = Math.floor(y1 + temp.umin * deltay + 0.5);
      return {
        x1,
        x2,
        y1,
        y2
      };
    }
-->

</html>